package ex2a.model.threads;

import java.util.Random;

import ex2a.controller.Controller;

public class ProducerThread extends Thread {
	
	private final String name = "ProducerThread";
	private String toString;
	private Controller controller;
	private int limit;
	private int readSemaphoreIndex, mutexSemaphoreIndex, writeSemaphoreIndex;
	private int semaphoreIndex;
	
	public ProducerThread(	int id, int limit,
							int mutexSemaphoreIndex, int writeSemaphoreIndex, int readSemaphoreIndex ) {
		
		this.semaphoreIndex = -1;
		this.limit = limit;
		this.readSemaphoreIndex = readSemaphoreIndex;
		this.mutexSemaphoreIndex = mutexSemaphoreIndex;
		this.writeSemaphoreIndex = writeSemaphoreIndex;
		
		controller = Controller.getInstance();
		toString = name.concat( Integer.toString( id ) );
	}
	
	@Override
	public void run() {
		Random r = new Random();
		int product = 0;
		
		while( limit > controller.fila.getTotalProduzido() ) {
			// Caso ele pause o programa ou minimize, parar a thread.
			synchronized( controller ) {
				if( ! controller.isRunning() ) {
					try {
						controller.wait();
					} catch (InterruptedException e) {}
				}
			}
			
			// WAIT(ESCRITA)
			try {
				semaphoreIndex = writeSemaphoreIndex;
				controller.semaphores[ writeSemaphoreIndex ].acquire();
				semaphoreIndex = -1;
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				
				try {
					// WAIT(MUTEX)
					semaphoreIndex = mutexSemaphoreIndex;
					controller.semaphores[ mutexSemaphoreIndex ].acquire();
					semaphoreIndex = -1;
				} catch( InterruptedException in ) {
				} catch( RuntimeException rt ) {
					rt.printStackTrace();
				} finally {
					
					try {
						
						product = r.nextInt(1000);
						controller.fila.produz( product );
						sleep( controller.speed );
						
					} catch( InterruptedException in ) {
						in.printStackTrace();
					}
					
					// SIGNAL(MUTEX)
					controller.semaphores[ mutexSemaphoreIndex ].release();
				
				}
				
				// SIGNAL(LEITURA)
				controller.semaphores[ readSemaphoreIndex ].release();
			}
		}
	}
	
	public int getSemaphoreIndex() {
		return semaphoreIndex;
	}
	
	@Override
	public String toString() {
		return toString;
	}
	
	public void write( String msg ) {
		System.out.println( toString.concat( ": " ).concat( msg ) );
	}
}
